package main

import (
	"encoding/json"
	"errors"

	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
)

// Asset 定义资产结构体
type Asset struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Info  string `json:"info"`
	Owner string `json:"owner"`
}

// SmartContract 定义智能合约结构体
type SmartContract struct {
}

// Init 链码初始化方法
func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
	return shim.Success(nil)
}

// Invoke 链码调用方法
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	fn, args := stub.GetFunctionAndParameters()
	var result []byte
	var err error
	if fn == "AddAsset" {
		result, err = s.AddAsset(stub, args)
	} else if fn == "TransferAsset" {
		result, err = s.TransferAsset(stub, args)
	} else if fn == "QueryAsset" {
		result, err = s.QueryAsset(stub, args)
	} else {
		return shim.Error("无效的函数名")
	}
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(result)
}

// AddAsset 创建资产
func (s *SmartContract) AddAsset(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	if len(args) != 4 {
		return nil, errors.New("参数数量错误，需要 4 个参数：ID, 名称, 信息, 所有者")
	}
	asset := Asset{
		ID:    args[0],
		Name:  args[1],
		Info:  args[2],
		Owner: args[3],
	}
	assetJSON, err := json.Marshal(asset)
	if err != nil {
		return nil, err
	}
	err = stub.PutState(args[0], assetJSON)
	if err != nil {
		return nil, err
	}
	return assetJSON, nil
}

// TransferAsset 转移资产
func (s *SmartContract) TransferAsset(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	if len(args) != 2 {
		return nil, errors.New("参数数量错误，需要 2 个参数：ID, 新所有者")
	}
	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return nil, err
	}
	if assetJSON == nil {
		return nil, errors.New("资产未找到")
	}
	var asset Asset
	err = json.Unmarshal(assetJSON, &asset)
	if err != nil {
		return nil, err
	}
	asset.Owner = args[1]
	updatedAssetJSON, err := json.Marshal(asset)
	if err != nil {
		return nil, err
	}
	err = stub.PutState(args[0], updatedAssetJSON)
	if err != nil {
		return nil, err
	}
	return updatedAssetJSON, nil
}

// QueryAsset 查询资产
func (s *SmartContract) QueryAsset(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("参数数量错误，需要 1 个参数：ID")
	}
	assetJSON, err := stub.GetState(args[0])
	if err != nil {
		return nil, err
	}
	if assetJSON == nil {
		return nil, errors.New("资产未找到")
	}
	return assetJSON, nil
}
